//
//  KSImageUtil.m
//  test
//
//  Created by Mac on 2018/12/29.
//

#import "KSImageUtil.h"
#import <Photos/Photos.h>

NSString * const PhotoAlbumToolErrorDomain = @"PhotoAlbumToolErrorDomain";

@implementation KSImageUtil

///MARK:-修正图片方向
UIImage* ks_imageDirection(UIImage* src){
    if (src.imageOrientation == UIImageOrientationUp)
        return src;
    
    CGAffineTransform transform = CGAffineTransformIdentity;
    
    switch (src.imageOrientation) {
        case UIImageOrientationDown:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, src.size.width, src.size.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;
            
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
            transform = CGAffineTransformTranslate(transform, src.size.width, 0);
            transform = CGAffineTransformRotate(transform, M_PI_2);
            break;
            
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, 0, src.size.height);
            transform = CGAffineTransformRotate(transform, -M_PI_2);
            break;
        default:
            break;
    }
    
    switch (src.imageOrientation) {
        case UIImageOrientationUpMirrored:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, src.size.width, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
            
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, src.size.height, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
        default:
            break;
    }
    
    CGContextRef ctx = CGBitmapContextCreate(NULL, src.size.width, src.size.height,
                                             CGImageGetBitsPerComponent(src.CGImage), 0,
                                             CGImageGetColorSpace(src.CGImage),
                                             CGImageGetBitmapInfo(src.CGImage));
    CGContextConcatCTM(ctx, transform);
    switch (src.imageOrientation) {
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            // Grr...
            CGContextDrawImage(ctx, CGRectMake(0,0,src.size.height,src.size.width), src.CGImage);
            break;
            
        default:
            CGContextDrawImage(ctx, CGRectMake(0,0,src.size.width,src.size.height), src.CGImage);
            break;
    }
    
    CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
    UIImage *img = [UIImage imageWithCGImage:cgimg];
    CGContextRelease(ctx);
    CGImageRelease(cgimg);
    return img;
}

///MARK:- base同步按质量压缩图片
NSData* ks_imageCompressQuality(UIImage* src, NSUInteger byte){
    src = _ksprepareImageSize(src);
    
    @autoreleasepool {
        NSData* imgData = UIImageJPEGRepresentation(src, 1);
        
        if (imgData.length < byte) {
            return imgData;
        }
        
        CGFloat max = 1;
        CGFloat min = 0.000001;
        CGFloat quality = (max + min) / 2;
        CGFloat lastLength = 0;
        
        while (byte - imgData.length > 1000 && lastLength != imgData.length) {
            
            lastLength = imgData.length;
            
            imgData = UIImageJPEGRepresentation(src, quality);
            
            if (imgData.length > byte) {
                max = quality;
            }else if (imgData.length < byte){
                min = quality;
            }
            quality = (max + min) / 2;
        }
        
        return imgData;
    }
}

///MARK: base同步按尺寸压缩图片
NSData* ks_imageCompressSize(UIImage* src ,NSUInteger byte){
    
    src = _ksprepareImageSize(src);
    
    @autoreleasepool {
        NSData* imgData = UIImageJPEGRepresentation(src, 1.0);;
        
        if (byte > imgData.length) {
            return imgData;
        }
        
        CGSize imgSize = src.size;
        CGFloat max = 1.0;
        CGFloat min = 0.1;
        CGFloat scale = (max + min) / 2;
        
        while (byte - imgData.length > 1000 && ABS(scale - min) >= 0.000001) {
            CGSize size = CGSizeMake(imgSize.width * scale, imgSize.height * scale);
            UIImage* img = ks_imageResize(src, size);
            imgData = UIImageJPEGRepresentation(img, 1.0);
            
            if (imgData.length > byte) {
                max = scale;
            }else if (imgData.length < byte){
                min = scale;
            }
            scale = (max + min) / 2;
        }
        
        return imgData;
    }
}


///MARK:- 异步批量压缩图片质量
void ks_imageAsynCompressQuality(NSArray<UIImage*>* srcs,
                                 NSUInteger byte,
                                 CompressImageComplete complete){
    
    dispatch_async(_kscompress_queue(), ^{
        
        NSArray<NSData*>* imgs = ks_imageSynCompressQuality(srcs, byte);
        
        if (complete) {
            complete(imgs);
        }
        
    });
}

///MARK:- 同步批量压缩图片质量
NSArray<NSData*>* ks_imageSynCompressQuality(NSArray<UIImage*>* srcs,
                                             NSUInteger byte){
    NSMutableArray<NSData*>* imgs = [NSMutableArray arrayWithCapacity:srcs.count];
    
    for (UIImage* src in srcs) {
        [imgs addObject:ks_imageCompressQuality(src, byte)];
    }
    
    return imgs;
}

///MARK:-异步批量压缩图片尺寸
void ks_imageAsynCompressSize(NSArray<UIImage*>* srcs,
                              NSUInteger byte,
                              CompressImageComplete complete){
    
    dispatch_async(_kscompress_queue(), ^{
        
        NSArray<NSData*>* imgs = ks_imageSynCompressSize(srcs, byte);
        
        if (complete) {
            complete(imgs);
        }
        
    });
}

///MARK:-同步批量压缩图片尺寸
NSArray<NSData*>* ks_imageSynCompressSize(NSArray<UIImage*>* srcs,
                                          NSUInteger byte){
    NSMutableArray<NSData*>* imgs = [NSMutableArray arrayWithCapacity:srcs.count];
    
    for (UIImage* src in srcs) {
        [imgs addObject:ks_imageCompressSize(src, byte)];
    }
    return imgs;
}

///MARK:-异步按质量和尺寸压缩图片
void ks_imageAsynCompress(NSArray<UIImage*>* srcs,
                          NSUInteger byte,
                          CompressImageComplete complete){
    dispatch_async(_kscompress_queue(), ^{
        
        NSArray<NSData*>* imgs = ks_imageSynCompress(srcs, byte);
        
        if (complete) {
            complete(imgs);
        }
        
    });
}

///MARK:-同步按质量和尺寸压缩图片
NSArray<NSData*>* ks_imageSynCompress(NSArray<UIImage*>* srcs,
                                      NSUInteger byte){
    
    NSMutableArray<NSData*>* imgs = [NSMutableArray arrayWithCapacity:srcs.count];
    
    for (UIImage* src in srcs) {
        
        NSData* data = ks_imageCompressQuality(src, byte);
        UIImage* img = [UIImage imageWithData:data];
        
        if (data.length > byte) {
            data = ks_imageCompressSize(img, byte);
        }
        
        [imgs addObject:data];
    }
    
    return imgs;
}

///MARK:-同步修改图片尺寸
UIImage* ks_imageResize(UIImage* src, CGSize size){
    
    UIGraphicsBeginImageContextWithOptions(size, NO, 0);

    [src drawInRect:CGRectMake(0, 0, size.width, size.height)];
    
    UIImage* img = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
        
    return img;
}

///MARK:-压缩前预先设置最大1024的尺寸
UIImage* _ksprepareImageSize(UIImage* src){
    
    CGSize srcSize = CGSizeMake(src.size.width * src.scale, src.size.height * src.scale);
    CGSize size = CGSizeZero;
    CGFloat max = 1024;
    BOOL shouldResize = NO;
    
    if (srcSize.width > srcSize.height) {
        if (srcSize.width > max) {
            size.width = max;
            size.height = max / srcSize.width * srcSize.height;
            shouldResize = YES;
        }
    }else if (srcSize.width < srcSize.height){
        if (srcSize.height > max) {
            size.height = max;
            size.width = max / srcSize.height * srcSize.width;
            shouldResize = YES;
        }
    }else{
        if (srcSize.width > max) {
            size.width = max;
            size.height = max;
            shouldResize = YES;
        }
    }
    if (shouldResize) {
        return ks_imageResize(src, size);
    }else{
        return src;
    }
}

///MARK:-从UIImage转换base64字符串
NSString* ks_imageToBase64(UIImage* src){
    if (!src) return nil;
    return [UIImagePNGRepresentation(src) base64EncodedStringWithOptions:kNilOptions];
}

///MARK:-从base64字符串转换UIImage
UIImage* ks_imageFromBase64(NSString* base64){
    if (!base64 || base64.length == 0) return nil;
    NSData* data = [[NSData alloc] initWithBase64EncodedString:base64 options:kNilOptions];
    if (!data) return nil;
    return [UIImage imageWithData:data];
}


///MARK:-获取异步线程
dispatch_queue_t _kscompress_queue(void){
    static dispatch_queue_t queue = NULL;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        queue = dispatch_queue_create("com.kscompress.queue", NULL);
    });
    return queue;
}

///MARK:-保存图片到相册
void ks_saveAssetToAlbum(NSURL* assetURL,SaveImageComplete completion){
    _saveAssetToAlbum(assetURL, completion);
}
void ks_saveDataToAlbum(NSData* data,SaveImageComplete completion){
    _saveAssetToAlbum(data, completion);
}
void _saveAssetToAlbum(id urlOrData,SaveImageComplete completion){
    
    [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
        if (status == PHAuthorizationStatusAuthorized) {
            PHPhotoLibrary *library = [PHPhotoLibrary sharedPhotoLibrary];
            [library performChanges:^{
                if ([urlOrData isKindOfClass:[NSURL class]]) {
                     [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:urlOrData];
                } else if ([urlOrData isKindOfClass:[NSData class]]) {
                    NSString *filePath = [NSTemporaryDirectory() stringByAppendingFormat:@"%@.png", [NSUUID UUID].UUIDString];
                    [(NSData *)urlOrData writeToFile:filePath atomically:NO];
                    [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:[NSURL fileURLWithPath:filePath]];
                }
            } completionHandler:^(BOOL success, NSError * _Nullable error) {
                if (completion) {
                    completion(success, error);
                }
            }];
        } else {
            NSError *error = [NSError errorWithDomain:PhotoAlbumToolErrorDomain
                                                 code:PhotoAlbumToolNotAuthorized
                                             userInfo:@{NSLocalizedFailureReasonErrorKey:@"无相册写入权限"}];
            if (completion) {
                completion(NO, error);
            }
        }
    }];
}
@end
